import org.jsecurity.authc.AuthenticationException
import org.jsecurity.authc.UsernamePasswordToken
import org.jsecurity.SecurityUtils


import uk.ac.soton.ecs.iam.grid.comms.client.AxisTransport;
import uk.ac.soton.ecs.iam.grid.comms.client.RemoteDataService;
import uk.ac.soton.itinnovation.grid.client.engine.impl.DefaultInvocationEngine;
import uk.ac.soton.itinnovation.grid.client.plugins.GridClientPluginManager;
import uk.ac.soton.itinnovation.grid.client.proxy.HelperProxyFactory;
import uk.ac.soton.itinnovation.grid.client.proxy.InvocationEngineProxyFactory;
import uk.ac.soton.itinnovation.grid.client.proxy.ServiceFactory;
import uk.ac.soton.itinnovation.grid.comms.client.ITInnovSocketFactory;
import uk.ac.soton.itinnovation.grid.comms.client.WSDLCacheImpl;
import uk.ac.soton.itinnovation.grid.comms.client.CertificateFileTrustValidator;
import uk.ac.soton.itinnovation.grid.utils.Identity;
import uk.ac.soton.itinnovation.grid.utils.IdentityProvider;
import uk.ac.soton.itinnovation.grid.utils.KeystoreIdentityProvider;
import uk.ac.soton.itinnovation.grid.utils.UsernameIdentityProvider;


class AuthController {
    def jsecSecurityManager

    def index = { redirect(action: 'login', params: params) }

    def login = {
        return [ username: params.username, rememberMe: (params.rememberMe != null), targetUri: params.targetUri ]
    }

    def signIn = {
        def authToken = new UsernamePasswordToken(params.email, params.password)

        // Support for "remember me"
        if (params.rememberMe) {
            authToken.rememberMe = true
        }

        try{
            // Perform the actual login. An AuthenticationException
            // will be thrown if the email is unrecognised or the
            // password is incorrect.
            this.jsecSecurityManager.login(authToken)

            session.user = auth.User.findWhere(email:params.email)
            def user = auth.User.findWhere(email:params.email)
      
            if (session.user)
            {
                IdentityProvider userIdp;       
                if (user.keystoreLocation == null)
                {
                    String ksDir = grailsApplication.config.gria.identity.keyStoreDir
                    user.keystoreLocation = ksDir + user.userName + ".ks";
                    user.save();
                }
                File keystoreFile = new File(user.keystoreLocation);
                if (!keystoreFile.exists()) {
                    println "Creating Keystore..."
                    KeystoreIdentityProvider issuerIdp = new KeystoreIdentityProvider(
                        grailsApplication.config.gria.identity.issuerKeystore, grailsApplication.config.gria.identity.issuerPassword.toCharArray());
                    Identity issuerId = issuerIdp.getIdentity();
                    userIdp = new UsernameIdentityProvider(user.email, grailsApplication.config.gria.identity.dnDomain,
                        user.email, user.password, issuerId.getPrivateKey(),
                        issuerId.getCertificate());
                    Identity id = userIdp.getIdentity(); 
                    id = userIdp.getIdentity()
                    println id          
                    id.saveKeyStore(keystoreFile)   
                } 
                else {
                    println "Existing Keystore found..."
                    userIdp = new KeystoreIdentityProvider(user.keystoreLocation,
                            user.password.toCharArray());   
                    Identity id = userIdp.getIdentity(); 
                    id = userIdp.getIdentity()
                    println id
                    }
            
                println "Creating serviceFactory..."
            
                AxisTransport myTransport = new AxisTransport(userIdp);
            
                myTransport.setCertificateTrustValidator(new CertificateFileTrustValidator(new File(grailsApplication.config.gria.identity.trustCertificateDir)));
            
                WSDLCacheImpl myWsdlCache = new WSDLCacheImpl(myTransport);
                InvocationEngineProxyFactory pf = new InvocationEngineProxyFactory(new DefaultInvocationEngine(myTransport), myWsdlCache);

                GridClientPluginManager gcpm = new GridClientPluginManager();
                gcpm.loadPlugins();
            
                user.helperProxyFactory = new HelperProxyFactory(pf,gcpm.getHelperRegistry());
            
                user.serviceFactory = new ServiceFactory(myWsdlCache, user.helperProxyFactory); 
            
                user.subjectDN = userIdp.getIdentity().getCertificate().getSubjectDN().toString();
                
                print user.subjectDN
                
                user.save()
               
                }
            // If a controller redirected to this page, redirect back
            // to it. Otherwise redirect to the root URI.
            def targetUri = params.targetUri ?: "/"

            log.info "Redirecting to '${targetUri}'."
            redirect(uri: targetUri)
        }
        catch (AuthenticationException ex){
            // Authentication failed, so display the appropriate message
            // on the login page.
            log.info "Authentication failure for user '${params.username}'."
            flash.message = message(code: "login.failed")

            // Keep the username and "remember me" setting so that the
            // user doesn't have to enter them again.
            def m = [ username: params.username ]
            if (params.rememberMe) {
                m['rememberMe'] = true
            }

            // Remember the target URI too.
            if (params.targetUri) {
                m['targetUri'] = params.targetUri
            }

            // Now redirect back to the login page.
            redirect(action: 'login', params: m)
        }
    }

    def signOut = {
        // Log the user out of the application.
        SecurityUtils.subject?.logout()

        // For now, redirect back to the home page.
        redirect(uri: '/')
    }

    def unauthorized = {
        render 'You do not have permission to access this page.'
    }
}
